package com.lijin.batchsys.framework.dao;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.lijin.batchsys.framework.common.AssertUtil;
import com.lijin.batchsys.framework.common.BatchUtil;
import com.lijin.batchsys.framework.dao.model.BatchExecLog;
import com.lijin.batchsys.framework.dao.model.BatchExecLogDetail;
import com.lijin.batchsys.framework.enums.RunningMode;
import com.lijin.batchsys.framework.enums.RunningStatus;

/**
 * Description: 记录批次日志的DAO
 * 
 * (C) Copyright of China UnionPay Co., Ltd. 2010.
 * 
 */
public class BatchLogDAO extends BaseDAO {
	
	/**
	 * 新增批次日志信息
	 * 
	 * @param batchExecLog
	 */
	@Transactional
	public void saveBatchExecLog(final BatchExecLog batchExecLog) {
		Assert.notNull(batchExecLog, "日志不能为null");
		
		this.getJdbcTemplate().update(BatchSysSQL.getInstance().fetchSQL(BatchSysSQL.SQL_INSERT_BATCH_EXECLOG), 
				new PreparedStatementSetter() {
					@Override
					public void setValues(PreparedStatement ps) throws SQLException {
						ps.setString(1, batchExecLog.getLogId());
						ps.setInt(2, batchExecLog.getBatchNo());
						ps.setString(3, batchExecLog.getRunningMode());
						ps.setString(4, batchExecLog.getBatchDate());
						Date now = new Date();
						ps.setString(5, BatchUtil.formatDateTo8Str(now));
						ps.setString(6, BatchUtil.formatDateTo17Str(now));
						ps.setString(7, batchExecLog.getEndTime());
						ps.setString(8, RunningStatus.RUNNING.getCode());
						ps.setString(9, batchExecLog.getExecMsg());
						ps.setTimestamp(10, new Timestamp(now.getTime()));
						ps.setTimestamp(11, new Timestamp(now.getTime()));
					}
		});
	}
	
	public void saveBatchExecLogDetail(final BatchExecLogDetail batchExecLogDetail) {
		Assert.notNull(batchExecLogDetail, "日志详情不能为null");
		
		this.getJdbcTemplate().update(BatchSysSQL.getInstance().fetchSQL(BatchSysSQL.SQL_INSERT_BATCH_EXECLOG_DETAIL), 
				new PreparedStatementSetter() {
					@Override
					public void setValues(PreparedStatement ps) throws SQLException {
						ps.setString(1, batchExecLogDetail.getLogDetailId());
						ps.setString(2, batchExecLogDetail.getLogId());
						ps.setInt(3, batchExecLogDetail.getBatchNo());
						ps.setInt(4, batchExecLogDetail.getJobNo());
						ps.setInt(5, batchExecLogDetail.getStepNo());
						ps.setString(6, batchExecLogDetail.getBatchDate());
						Date now = new Date();
						ps.setString(7, BatchUtil.formatDateTo8Str(now));
						ps.setString(8, BatchUtil.formatDateTo17Str(now));
						ps.setString(9, batchExecLogDetail.getEndTime());
						ps.setString(10, RunningStatus.RUNNING.getCode());
						ps.setString(11, batchExecLogDetail.getExecMsg());
						ps.setString(12, batchExecLogDetail.getErrMsg());
						ps.setTimestamp(13, new Timestamp(now.getTime()));
						ps.setTimestamp(14, new Timestamp(now.getTime()));
					}
		});
	}
	
	/**
	 * 更新批次日志信息
	 * 
	 * @param batchLog
	 */
	public void updatebatchExecLog(final BatchExecLog batchLog) {
		Assert.notNull(batchLog);
		Assert.notNull(batchLog.getLogId());
		Assert.notNull(batchLog.getStatus());
		Assert.notNull(batchLog.getExecMsg());
		
		this.getJdbcTemplate().update(BatchSysSQL.getInstance().fetchSQL(BatchSysSQL.SQL_UPDATE_BATCH_EXEC_LOG), 
				new PreparedStatementSetter() {
					@Override
					public void setValues(PreparedStatement ps) throws SQLException {
						ps.setString(1, batchLog.getStatus());
						Date now = new Date();
						ps.setString(2, batchLog.getEndTime());
						ps.setString(3, batchLog.getExecMsg());
						ps.setTimestamp(4, new Timestamp(now.getTime()));
						ps.setString(5, batchLog.getLogId());
					}
		});
	}
	
	/**
	 * 更新批次日志详情
	 * @param batchLogDetail
	 */
	public void updateBatchExecLogDetail(final BatchExecLogDetail batchLogDetail) {
		
		AssertUtil.objIsNull(batchLogDetail, "日志详情记录为null");
		AssertUtil.strIsBlank(batchLogDetail.getLogDetailId(), "日志详情记录id为空");
		AssertUtil.objIsNull(batchLogDetail.getStatus(), "日志详情记录状态为null");
		AssertUtil.objIsNull(batchLogDetail.getExecMsg(), "日志详情记录描述为null");
		AssertUtil.objIsNull(batchLogDetail.getErrMsg(), "日志详情记录错误信息为null");
		
		this.getJdbcTemplate().update(BatchSysSQL.getInstance().fetchSQL(BatchSysSQL.SQL_UPDATE_BATCH_EXEC_LOG_DETAIL), 
				new PreparedStatementSetter() {
					@Override
					public void setValues(PreparedStatement ps) throws SQLException {
						ps.setString(1, batchLogDetail.getStatus()); // 状态
						ps.setString(2, batchLogDetail.getEndTime()); // 修改时间
						ps.setString(3, batchLogDetail.getExecMsg()); // 描述
						ps.setString(4, batchLogDetail.getErrMsg()); // 错误信息
						ps.setTimestamp(5, new Timestamp((new Date()).getTime())); // 记录更新时间
						ps.setString(6, batchLogDetail.getLogDetailId()); // 主键
					}
		});
	}
	
	/**
	 * 根据ID查找批次日志记录
	 * @param id
	 * @return
	 */
	public BatchExecLog queryBatchExecLogById(final String id) {
		return this.getJdbcTemplate().query(BatchSysSQL.getInstance().fetchSQL(BatchSysSQL.SQL_SEL_BATCH_EXECLOG_BY_ID), 
				new PreparedStatementSetter() {
					@Override
					public void setValues(PreparedStatement ps) throws SQLException {
						ps.setString(1, id);
					}
				}, 
				new ResultSetExtractor<BatchExecLog>() {
					@Override
					public BatchExecLog extractData(ResultSet rs) throws SQLException, DataAccessException {
						if (rs.next()) {
							BatchExecLog execLog = new BatchExecLog();
							execLog.setLogId(rs.getString("LOG_ID"));
							execLog.setBatchNo(rs.getInt("BATCH_NO"));
							execLog.setRunningMode(rs.getString("RUNNING_MODE"));
							execLog.setBatchDate(rs.getString("BATCH_DATE"));
							execLog.setRunningDate(rs.getString("RUNNING_DATE"));
							execLog.setStartTime(rs.getString("START_TIME"));
							execLog.setEndTime(rs.getString("END_TIME"));
							execLog.setStatus(rs.getString("STATUS"));
							execLog.setExecMsg(rs.getString("EXEC_MSG"));
							execLog.setRecCrtTs(rs.getDate("REC_CRT_TS"));
							execLog.setRecUpdTs(rs.getDate("REC_UPD_TS"));
							return execLog;
						}
						return null;
					}
		});
	}
	
	/**
	 * 根据ID查找批次日志详情记录
	 * @param id
	 * @return
	 */
	public BatchExecLogDetail queryBatchExecLogDetailById(final String id) {
		return this.getJdbcTemplate().query(BatchSysSQL.getInstance().fetchSQL(BatchSysSQL.SQL_SEL_BATCH_EXECLOG_DETAIL_BY_ID), 
				new PreparedStatementSetter() {
					@Override
					public void setValues(PreparedStatement ps) throws SQLException {
						ps.setString(1, id);
					}
				}, 
				new ResultSetExtractor<BatchExecLogDetail>() {
					@Override
					public BatchExecLogDetail extractData(ResultSet rs) throws SQLException, DataAccessException {
						if (rs.next()) {
							BatchExecLogDetail execLogDetail = new BatchExecLogDetail();
							execLogDetail.setLogDetailId(rs.getString("LOG_DETAIL_ID"));
							execLogDetail.setLogId(rs.getString("LOG_ID"));
							execLogDetail.setBatchNo(rs.getInt("BATCH_NO"));
							execLogDetail.setJobNo(rs.getInt("JOB_NO"));
							execLogDetail.setStepNo(rs.getInt("STEP_NO"));
							execLogDetail.setBatchDate(rs.getString("BATCH_DATE"));
							execLogDetail.setRunningDate(rs.getString("RUNNING_DATE"));
							execLogDetail.setStartTime(rs.getString("START_TIME"));
							execLogDetail.setEndTime(rs.getString("END_TIME"));
							execLogDetail.setStatus(rs.getString("STATUS"));
							execLogDetail.setExecMsg(rs.getString("EXEC_MSG"));
							execLogDetail.setErrMsg(rs.getString("ERR_MSG"));
							execLogDetail.setRecCrtTs(rs.getDate("REC_CRT_TS"));
							execLogDetail.setRecUpdTs(rs.getDate("REC_UPD_TS"));
							
							return execLogDetail;
						}
						return null;
					}
		});
	}
	
	/**
	 * (没有添加断点功能)根据批次ID查找批次日志详情列表
	 * @param runningMode 
	 * @return
	 */
	public List<BatchExecLogDetail> queryBatchLogDetailsByExecId(final String batcExecLogId) {
		final List<BatchExecLogDetail> logDetails = new ArrayList<BatchExecLogDetail>();
		
		this.getJdbcTemplate().query(BatchSysSQL.getInstance().fetchSQL(BatchSysSQL.SQL_SEL_BATCH_EXECLOG_DETAIL_BY_BATCH_LOG_ID), 
				new PreparedStatementSetter() {
					@Override
					public void setValues(PreparedStatement ps) throws SQLException {
						ps.setString(1, batcExecLogId);
					}
				},
				new RowCallbackHandler() {
					@Override
					public void processRow(ResultSet rs) throws SQLException {
						BatchExecLogDetail logDetail = new BatchExecLogDetail();
						logDetail.setLogDetailId(rs.getString("ID"));
						logDetail.setLogId(rs.getString("BATCH_LOG_ID"));
						logDetail.setBatchNo(rs.getInt("BATCH_NO"));
						logDetail.setJobNo(rs.getInt("JOB_NO"));
						logDetail.setStepNo(rs.getInt("STEP_NO"));
						logDetail.setBatchDate(rs.getString("BATCH_DATE"));
						logDetail.setStartTime(rs.getString("START_TIME"));
						logDetail.setEndTime(rs.getString("END_TIME"));
						logDetail.setStatus(rs.getString("STATUS"));
						logDetail.setExecMsg(rs.getString("DESC"));
						logDetail.setErrMsg(rs.getString("ERR_MSG"));
						logDetails.add(logDetail);
					}
		});
		return logDetails;
	}
	
	/**
	 * (添加断点功能)根据批次ID查找批次日志详情列表
	 * @param runningMode 
	 * @return
	 */
	public List<BatchExecLogDetail> queryBatchLogDetailsByExecId(final String batcExecLogId, RunningMode batchRunningMode) {
		final List<BatchExecLogDetail> logDetails = new ArrayList<BatchExecLogDetail>();
		
		this.getJdbcTemplate().query(BatchSysSQL.getInstance().fetchSQL(BatchSysSQL.SQL_SEL_BATCH_EXECLOG_DETAIL_BY_BATCH_LOG_ID), 
				new PreparedStatementSetter() {
					@Override
					public void setValues(PreparedStatement ps) throws SQLException {
						ps.setString(1, batcExecLogId);
					}
				},
				new RowCallbackHandler() {
					@Override
					public void processRow(ResultSet rs) throws SQLException {
						BatchExecLogDetail logDetail = new BatchExecLogDetail();
						logDetail.setLogDetailId(rs.getString("ID"));
						logDetail.setLogId(rs.getString("BATCH_LOG_ID"));
						logDetail.setBatchNo(rs.getInt("BATCH_NO"));
						logDetail.setJobNo(rs.getInt("JOB_NO"));
						logDetail.setStepNo(rs.getInt("STEP_NO"));
						logDetail.setBatchDate(rs.getString("BATCH_DATE"));
						logDetail.setStartTime(rs.getString("START_TIME"));
						logDetail.setEndTime(rs.getString("END_TIME"));
						logDetail.setStatus(rs.getString("STATUS"));
						logDetail.setExecMsg(rs.getString("DESC"));
						logDetail.setErrMsg(rs.getString("ERR_MSG"));
						
						logDetails.add(logDetail);
					}
		});
		
		//组装异常处理功能
		BatchUtil.buildOperate(logDetails, batchRunningMode);
		
		return logDetails;
	}

	/**
	 * 根据批次ID查找批次日志详情列表
	 * @return
	 */
	public List<BatchExecLog> queryAllBatchLog( ) {
		final List<BatchExecLog> logs = new ArrayList<BatchExecLog>();
		this.getJdbcTemplate().query(BatchSysSQL.getInstance().fetchSQL(BatchSysSQL.SQL_SEL_ALL_BATCH_EXECLOG), 
			new RowCallbackHandler() {
				@Override
				public void processRow(ResultSet rs) throws SQLException {
					BatchExecLog execLog = new BatchExecLog();
					execLog.setLogId(rs.getString("ID"));
					execLog.setRunningMode(rs.getString("RUNNING_MODE"));
					execLog.setBatchNo(rs.getInt("BATCH_NO"));
					execLog.setBatchDate(rs.getString("BATCH_DATE"));
					execLog.setStartTime(rs.getString("START_TIME"));
					execLog.setEndTime(rs.getString("END_TIME"));
					execLog.setStatus(rs.getString("STATUS"));
					execLog.setExecMsg(rs.getString(""));
					
					logs.add(execLog);
				}
		});
		return logs;
	}

	/**
	 * 详细日志总数，通过logID
	 * @return
	 */
	public int getLogDetailCount(String batcExecLogId) {
		
		Object[] parameters = new Object[] {batcExecLogId};
		int count = getJdbcTemplate().queryForInt(BatchSysSQL.getInstance().fetchSQL(BatchSysSQL.SQL_SEL_COUNT_DETAIL_LOGID), 
				parameters, new int[] { Types.CHAR });
		return count;
	}

	
	@SuppressWarnings("unchecked")
	public <T> List<T> listPageInfo(String sql, final int firstResult, final int endResult) {
		final List<BatchExecLog> logs = new ArrayList<BatchExecLog>();
		
		this.getJdbcTemplate().query(sql, 
		 new PreparedStatementSetter() {
			@Override
		   public void setValues(PreparedStatement ps) throws SQLException {
				ps.setLong(1, firstResult);
				ps.setLong(2, endResult);
			}
		},
		new RowCallbackHandler() {
			@Override
			public void processRow(ResultSet rs) throws SQLException {
				BatchExecLog execLog = new BatchExecLog();
				execLog.setLogId(rs.getString("ID"));
				execLog.setRunningMode(rs.getString("RUNNING_MODE"));
				execLog.setBatchNo(rs.getInt("BATCH_NO"));
				execLog.setBatchDate(rs.getString("BATCH_DATE"));
				execLog.setStartTime(rs.getString("START_TIME"));
				execLog.setEndTime(rs.getString("END_TIME"));
				execLog.setStatus(rs.getString("STATUS"));
				execLog.setExecMsg(rs.getString("DESC"));
				
				logs.add(execLog);
			}
		});
		
		return (List<T>) logs;
	}
	
	public int getCount(String countSql) {
		int count = this.getJdbcTemplate().queryForInt(countSql);
		return count;
	}
}
